import com.lefu.utils.common.excelhelper.ExcelRead;
import com.lefu.utils.common.excelhelper.ExcelWrite;
import com.lefu.utils.common.excelhelper.Head;
import com.lefu.utils.common.exception.LefuException;
import org.apache.commons.lang.StringUtils;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;

import java.io.*;
import java.util.ArrayList;
import java.util.List;

/**
 * Created by lrs on 2018/2/24.
 */
public class Product {
    /**
     * 读取断点文件
     * @return
     * @throws java.io.IOException
     */
    private String readBreakpoint() throws IOException {
        InputStreamReader reader = new InputStreamReader(new FileInputStream("./output/breakpoint")); // 建立一个输入流对象reader
        BufferedReader br = new BufferedReader(reader); // 建立一个对象，它把文件内容转成计算机能读懂的语言
        String line = "";
        line = br.readLine();
        br.close();
        reader.close();
        return line;
    }

    /**
     * 写入断点文件
     * @param subCategoryFile
     * @throws IOException
     */
    private void writeBreakpoint(String subCategoryFile) throws IOException {
        File writename = new File("./output/breakpoint"); // 相对路径，如果没有则要建立一个新的output。txt文件
        writename.createNewFile(); // 创建新文件
        BufferedWriter out = new BufferedWriter(new FileWriter(writename));
        out.write(subCategoryFile); // \r\n即为换行
        out.flush(); // 把缓存区内容压入文件
        out.close(); // 最后记得关闭文件
    }

    /**
     * 得到产品轮播图
     * @param doc
     * @return
     */
    private String getImgURL(Document doc) {
        StringBuffer sb = new StringBuffer();
        Elements product = doc.select("div .padding_top20").eq(0); // 通过选择器得到全部产品分类
        Elements es = product.select(".bigImg li img"); // 取得所有img连接
        for (Element e : es) {
            sb.append(e.attr("src")); // 拼接图片url
            sb.append("|");
        }
        return sb.toString();
    }
    /**
     * 创建产品excel
     * @return
     * @throws com.lefu.utils.common.exception.LefuException
     */
    public ExcelWrite createProductExcel() throws LefuException {
        ExcelWrite excelWrite = new ExcelWrite();
        Head head;
        // 一级分类
        head = new Head(0, "一级分类", 25, null);
        excelWrite.addHead(head);
        // 二级分类
        head = new Head(1, "二级分类", 25, null);
        excelWrite.addHead(head);
        // 三级分类
        head = new Head(2, "三级分类", 25, null);
        excelWrite.addHead(head);
        // 三级分类 ID
        head = new Head(3, "三级分类ID", 12, null);
        excelWrite.addHead(head);
        // 二级分类 URL
        head = new Head(4, "二级分类ID", 12, null);
        excelWrite.addHead(head);
        // 产品ID
        head = new Head(5, "产品ID", 12, null);
        excelWrite.addHead(head);
        // 产品名称
        head = new Head(6, "产品名称", 25, null);
        excelWrite.addHead(head);
        // 产品单价
        head = new Head(7, "产品单价", 10, null);
        excelWrite.addHead(head);
        // 二级分类 URL
        head = new Head(8, "产品URL", 50, null);
        excelWrite.addHead(head);
        // 产品名
        head = new Head(9, "产品名", 50, null);
        excelWrite.addHead(head);
        // 产品子名称
        head = new Head(10, "产品子名称", 50, null);
        excelWrite.addHead(head);
        // 品牌
        head = new Head(11, "品牌", 50, null);
        excelWrite.addHead(head);
        // 特点
        head = new Head(12, "特点", 50, null);
        excelWrite.addHead(head);
        // 规格
        head = new Head(13, "规格", 50, null);
        excelWrite.addHead(head);
        // 轮播图URL
        head = new Head(14, "轮播图URL", 50, null);
        excelWrite.addHead(head);

        return excelWrite;
    }

    /**
     * 爬取产品页
     * @throws Exception
     */
    public void spiderProduct() throws Exception {
        // 读取断点文件，并且计算上一次失败位置
        String breakpoint = readBreakpoint();
        String breakFileName;
        if ("Product".equals(breakpoint)) {
            breakFileName = "";
        } else if (breakpoint.indexOf("subCategory_LsTypeSysNo_") != -1) {
            breakFileName = breakpoint;
        } else {
            return;
        }

        // 返回子分类所有文件
        FileHelp fileHelp = new FileHelp();
        List<String> subCategoryFiles = fileHelp.getAllFile("./output", "subCategory_LsTypeSysNo_");

        for (String subCategoryFile : subCategoryFiles) {
            // 判断如果之前断了则眺到下一个爬取
            if (!StringUtils.isEmpty(breakFileName)) {
                if (!breakFileName.equals(subCategoryFile)) {
                    continue;
                }
            }
            // 清除断点文件记录变量
            breakFileName = "";

            writeBreakpoint(subCategoryFile); // 将当前爬取记录计入断点文件

            System.out.println("====================================================");
            System.out.println("开始爬取 " + subCategoryFile + "下的所有产品");

            FileOutputStream fos = new FileOutputStream(subCategoryFile.replace("subCategory", "Product")); // 将 subCategory_LsTypeSysNo_6_SysNo_2.xls 文件名生成类似 Product_LsTypeSysNo_100_SysNo_60.xls 的文件名保存产品信息
            ExcelWrite excelWrite = this.createProductExcel();

            // 读取主分类excel文件
            File file = new File(subCategoryFile);
            FileInputStream fis = new FileInputStream(file);
            ExcelRead excelReader = new ExcelRead(fis);
            while (excelReader.next()) {
                System.out.println("爬取产品信息：" + excelReader.getString("产品URL"));

                Document doc = Jsoup.connect(excelReader.getString("产品URL")).get(); // 加载产品页

                // 轮播图URL
                String imgURL = getImgURL(doc);

                // 产品名称
                Elements product = doc.select("div .padding_top20").eq(0); // 通过选择器得到产品
                // 得到产品子名称
                Elements subName = product.select(".font_weight.border_bottom03 span");
                String subProductName = subName.text();
                // 产品名
                Elements name = product.select(".font_weight.border_bottom03");
                String productName = name.text().replace(subProductName, "");

                // 品牌
                Elements brand = product.select("span.padding_left16");
                String brandName = brand.text();

                // 特点 规格
                Elements featuresAndSpec = product.select("div.line_height20.padding_left16");
                String features = featuresAndSpec.eq(0).html();
                String spec = featuresAndSpec.eq(1).html();

                // 描述
                StringBuffer productDescSB = new StringBuffer(); // 产品描述
                Elements productDesc = doc.select("div.padding_bottom20 table"); // 通过选择器得到产品
                productDescSB.append(productDesc.toString());
                Elements productDescSub = doc.select("div.padding_bottom10"); // 通过选择器得到产品
                for (Element e : productDescSub) {
                    if (e.childNodeSize() == 1) {
                        productDescSB.append(e.toString());
                    }
                }

                ArrayList<String> list = excelReader.getCurrentData();
                list.add(productName);
                list.add(subProductName);
                list.add(brandName);
                list.add(features);
                list.add(spec);
                list.add(imgURL);
                fileHelp.writeFile("./output/desc/"+excelReader.getString("产品ID")+".html", productDescSB.toString());

                excelWrite.addBody(list);
            }
            // 每请求完一个分类写一次文件
            excelWrite.write(fos);
            fos.close();
        }

        // 标记产品正常处理完成，开始合并产品表
        fileHelp = new FileHelp();
        fileHelp.writeFile("./output/breakpoint", "MergeProduct");
    }

    /**
     * 合并产品信息
     * @throws IOException
     */
    public void mergeProduct() throws Exception {
        // 读取断点文件，并且计算上一次失败位置
        String breakpoint = readBreakpoint();
        if (!"MergeProduct".equals(breakpoint)) {
            return;
        }

        System.out.println("========================================");
        System.out.println("开始合并产品表");

        // 返回子分类所有文件
        FileHelp fileHelp = new FileHelp();
        List<String> categoryProducts = fileHelp.getAllFile("./output", "Product_LsTypeSysNo_");

        ExcelWrite excelWrite = this.createProductExcel();

        for (String categoryProduct : categoryProducts) {
            System.out.println(categoryProduct);

            File file = new File(categoryProduct);
            FileInputStream fis = new FileInputStream(file);
            ExcelRead excelReader = new ExcelRead(fis);

            while (excelReader.next()) {
                excelWrite.addBody(excelReader.getCurrentData());
            }

        }

        // 写入合并后的文件
        FileOutputStream fos = new FileOutputStream("./output/Product.xls");
        excelWrite.write(fos);
        fos.close();

        System.out.println("产品表合并完成！！！");

        // 标记产品正常处理完成，开始合并产品表
        fileHelp = new FileHelp();
        fileHelp.writeFile("./output/breakpoint", "DownloadImg,0");
    }

}
